package session;

import entity.Item;
import entity.Wish;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

/**
 * Rappresenta il gestore delle transazioni degli entity Wish.
 *
 * @author Rachid Ouchary, Fabio Strocco, Max Passaghe, Marco Tansini.
 */
@Stateless
public class WishFacade implements WishFacadeRemote {
    @PersistenceContext(unitName = "WishLister-ejbPU")
    private EntityManager em;
    @EJB
    private ItemFacadeRemote itemFacade;

    /**
     * Rende persistente un nuovo desiderio.
     *
     * @param wish il desiderio da rendere persistente.
     */
    public void create(Wish wish) {
        em.persist(wish);
    }

    /**
     * Aggiorna lo stato del desiderio nel DB allo stato dell desiderio passato
     * come parametro.
     *
     * @param wish il desiderio da aggiornare.
     */
    public void edit(Wish wish) {
        em.merge(wish);
    }

    /**
     * Rimuove un desiderio dal DB.
     *
     * @param wish il desiderio da rimuovere.
     */
    public void remove(Wish wish) {
        em.remove(em.merge(wish));
    }

    /**
     * Carica il desiderio con l'id specificato.
     *
     * @param id l'id del desiderio da caricare.
     * @return il desiderio con l'id specificato, <code>null</code> se non esiste nel
     * DB.
     */
    public Wish find(Long id) {
        return em.find(Wish.class, id);
    }

    /**
     * Cerca il desiderio nel database e lo restituice.
     * Questo metodo &egrave utile se desiderio passato come parametro &egrave
     * null.
     *
     * @param wish il desiderio da cercare nel database.
     * @return il desiderio passato come parametro con id != null o <code>null</code>
     * se il desiderio non esiste nel database.
     */
    public Wish findWish(Wish wish) {
        Item item = wish.getItem();
        Query query = em.createNamedQuery(Wish.FIND_WISH);
        /*query.setParameter("priority", wish.getPriority());
        query.setParameter("voto", wish.getVoto());
        query.setParameter("prenotato", wish.isPrenotato());*/
        query.setParameter("item", (item.getId() == null ?
                                    itemFacade.findBy(item.getCategoria(), item.getDescrizione()) :
                                    item));
        query.setParameter("utente", wish.getUtente());

        try {
            return (Wish) query.getSingleResult();
        } catch (NoResultException ex) {
            return null;
        }
    }

    /**
     * Modifica il desiderio.
     *
     * @param wish il desiderio da modificare.
     * @param priority la nuova priorit&agrave del desiderio.
     * @param voto il nuovo voto del desiderio.
     */
    public void modificaDesiderio(Wish wish, Integer priority, Integer voto) {
        wish.setPriority(priority);
        wish.setVoto(voto);
        edit(wish);
    }

    /**
     *
     * @return
     */
    public List<Wish> findAll() {
        CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
        cq.select(cq.from(Wish.class));
        return em.createQuery(cq).getResultList();
    }

    /**
     *
     * @param range
     * @return
     */
    public List<Wish> findRange(int[] range) {
        CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
        cq.select(cq.from(Wish.class));
        Query q = em.createQuery(cq);
        q.setMaxResults(range[1] - range[0]);
        q.setFirstResult(range[0]);
        return q.getResultList();
    }

    /**
     * Prenota il desiderio.
     *
     * @param wish il desiderio.
     */
    public void prenota(Wish wish) {
        wish.prenota();
        edit(wish);
    }

    /**
     *
     * @return
     */
    public int count() {
        CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
        Root<Wish> rt = cq.from(Wish.class);
        cq.select(em.getCriteriaBuilder().count(rt));
        Query q = em.createQuery(cq);
        return ((Long) q.getSingleResult()).intValue();
    }
}
